首页/ 学科题库/ webgl/ WebGL 索引组网与面剔除
webgl 实战教程

WebGL 索引组网与面剔除

2026-09-13 约 8 分钟 juanwangdev

WebGL 索引组网与面剔除

一句话结论:索引决定网格怎么拼,缠绕顺序决定哪一面朝外,面剔除据此丢弃背面三角形以省掉一半绘制量。

索引组网与顶点缠绕顺序

是什么

索引组网是用索引数组描述三角形由哪些顶点组成的方式,缠绕顺序是这三个顶点在索引中的排列方向。WebGL 默认把屏幕空间下逆时针(CCW)排列的三角形判定为正面。

解决什么问题

它解决网格拓扑的表达与正反面判定问题。索引让顶点可以共享,避免重复存储;缠绕顺序则给每个面定义了法向,使背面剔除、双面材质与法线计算都有依据。

为什么这样做

三维网格中一个顶点通常被多个三角形共用,用索引表达拓扑可以把顶点数降到接近网格点数。而正反面判定需要一致的规则,采用投影后的有向面积符号判断既简单又可由硬件并行完成,因此成为图形 API 的通用约定。

怎么用

JavaScript
// 矩形:4 个顶点,逆时针缠绕表示正面朝向观察者
const positions = new Float32Array([
  -0.5, -0.5, 0,   // 0 左下
   0.5, -0.5, 0,   // 1 右下
   0.5,  0.5, 0,   // 2 右上
  -0.5,  0.5, 0,   // 3 左上
]);
const indices = new Uint16Array([
  0, 1, 2,   // 逆时针
  0, 2, 3,
]);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

计算方式:把三个顶点投影到屏幕,用叉积的 z 分量判断方向,正值通常对应逆时针。

常见坑

  • 索引顺序写反导致面被剔除 → 原因:缠绕方向与默认 CCW 相反 → 处理:调整索引顺序或设置 frontFace(CW)
  • 顶点共享后法线被平均 → 原因:平滑着色与硬边冲突 → 处理:硬边处拆分顶点
  • 索引超出顶点范围 → 原因:索引从 0 起算 → 处理:最大索引等于顶点数减一
  • 网格存在孤立三角形 → 原因:拓扑拼接遗漏 → 处理:生成时按行列统一构造索引

面剔除与可见性控制

是什么

面剔除是开启 CULL_FACE 后由 GPU 丢弃背面三角形的功能,配合 cullFace(剔除正面、背面或双面)与 frontFace(正面判定方向)共同控制哪些面参与绘制。

解决什么问题

它解决封闭物体背面被无意义绘制的问题。立方体、角色这类封闭网格的背面必然被前面遮挡,若照常光栅化,会造成大量无效的片元着色与深度写入。

为什么这样做

背面剔除发生在图元装配之后、光栅化之前,几乎零成本就能丢弃约一半三角形。相比深度测试的"先画再丢弃",剔除直接避免了后续所有计算,是性价比最高的几何阶段优化之一。

怎么用

JavaScript
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.BACK);        // 丢弃背面(默认)
gl.frontFace(gl.CCW);        // 逆时针为正面(默认)

// 需要看到内壁时改为剔除正面,或临时关闭
gl.cullFace(gl.FRONT);
gl.disable(gl.CULL_FACE);
设置行为
CULL_FACE + BACK丢弃背面,最常用
CULL_FACE + FRONT丢弃正面,用于看内壁
FRONT_AND_BACK全部丢弃,仅用于生成阴影图等特殊场景
未开启 CULL_FACE正反面都绘制

常见坑

  • 开启后模型整体消失 → 原因:缠绕顺序反了 → 处理:先关剔除确认模型,再修正索引或 frontFace
  • 平面图形被剔除 → 原因:单面片没有厚度 → 处理:平面类物体关闭剔除或使用双面材质
  • 镜像变换后正反面颠倒 → 原因:负缩放翻转了缠绕方向 → 处理:变换后重设 frontFace 或避免负缩放
  • 透明物体内部看不到 → 原因:剔除掉了背面 → 处理:两趟绘制背正面并排序

要点总结

  • 索引描述拓扑,缠绕顺序描述朝向,默认逆时针为正面
  • 索引从 0 起算,最大索引等于顶点数减一
  • 面剔除几乎零成本,可省掉封闭网格约一半的绘制量
  • 模型消失先关剔除排查,再修索引方向或 frontFace
  • 平面与透明物体需要关闭剔除或分两趟绘制

常见问题

什么是顶点缠绕顺序?

指三角形三个顶点被定义的先后方向。从观察者角度看为逆时针称为 CCW,顺时针称为 CW,WebGL 默认把逆时针面判定为正面。

开启面剔除后模型不见了怎么办?

多半是缠绕顺序与默认设置相反。检查索引顺序是否按逆时针排列,或用 gl.frontFace(gl.CW) 修改正面判定,临时排查时可先关闭剔除确认模型本身正常。

面剔除能带来多少性能提升?

封闭网格中约一半的三角形是背面,剔除后片元着色器的执行量与光栅化负载大致减半,对高面数模型与移动端提升明显。

半透明物体适合开面剔除吗?

不适合直接开启。透明物体需要看到内部与背面,通常做法是分两趟绘制,先画背面再画正面,或直接关闭剔除并按深度排序绘制。

想在手机上练这篇的配套题目?
使用微信 卷王开发者小程序/App,首页顶部扫一扫识别下方二维码,即可解锁本讲对应真题与错题本。
了解产品 App
← 上一篇 WebGL 绘制类型与参数化顶点生成 下一篇 → WebGL 鼠标与触摸交互映射